/**
 * 作用域函数:run 、 with 、T.run 、 T.apply 、 T.also 、 T.let
 * 优先选择标准按顺序：
 * 1、需要返回自己本身
 *      a.传递this 使用T.apply()
 *      b.专递it 使用 T.also()
 * 2、不需要返回自己本身
 *      a.需要扩展函数
 *          1.传递this 使用T.run()
 *          2.传递it 使用T.let()
 *      b.不过需要扩展函数
 *          1.传递this 使用with()
 *          2.不传递this 使用run()
 *
 */
fun main(args: Array<String>) {
    returnYourself()

    noReturnYourself()
}

/**
 * 返回自己本身
 */
fun returnYourself() {
    val str = "Return Yourself"

    //返回自己本身
    var any = str.apply {
        //传递this
        println(this)
        this.length//不影响返回类型
    }

    println("T.apply():${any.javaClass}")

    //返回自己本身
    any = str.also {
        //传递it
        println(it)
        it.length//不影响返回类型
    }

    println("T.also():${any.javaClass}")
}

/**
 * 不需要返回自己本身
 */
fun noReturnYourself() {

    //需要扩展
    needExtenstion()

    //不需要扩展
    noNeedExtenstion()
}

/**
 * 需要扩展
 */
fun needExtenstion() {
    val str = "Need Extenstion"
    //返回类型为kotlin.Unit
    var any = str.run {
        //传递this
        println(this)
        this.length//影响返回类型
    }

    println("T.run():${any.javaClass}")

    //返回类型为kotlin.Unit
    any = str.let {
        //传递this
        println(it)
        it.length//影响返回类型
    }

    println("T.let():${any.javaClass}")
}

/**
 * 不需要扩展
 */
fun noNeedExtenstion() {
    val str = "No Need Extenstion"
    //返回类型为kotlin.Unit
    var any = with(str) {
        //传递this
        println(this)
        this.length//影响返回类型
    }

    println("with():${any.javaClass}")

    //返回类型为boolean
    val result = run {
        val str = false//作用域改变，重新声明str
        //无参
        println(str)
        str//影响返回类型
    }

    println("run():${result.javaClass}")
}